﻿using System;
using System.Collections.Generic;
using System.Windows.Forms;
using Assist;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Plumbing;
using Autodesk.Revit.Exceptions;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using YArchitech.Controls;
using YArchitech.LIB;
using YArchitech.Revit;
using YArchitech.Temp;

namespace YArchitech.Plumbing
{
	[Transaction(TransactionMode.Manual)]
	[Regeneration(RegenerationOption.Manual)]
	public class HYPlumbingAutoDesignNew : HYNoTranExternalCommand
	{
		public override Result HYExecute()
		{
			ViewPlan viewPlan = base.Doc.ActiveView as ViewPlan;
			if (viewPlan == null || (int)viewPlan.ViewType != 1)
			{
				string text = "请在平面视图下运行该命令！";
				YJKMessageBox.Show(text);
				return Autodesk.Revit.UI.Result.Failed;
			}
			FormAutoDesign formAutoDesign = new FormAutoDesign(base.Doc);
			Result result;
			try
			{
				PlumbSystemAutoDesign plumbSystemAutoDesign;
				for (;;)
				{
					DialogResult dialogResult = formAutoDesign.ShowDialog();
					plumbSystemAutoDesign = new PlumbSystemAutoDesign(base.Doc);
					if (dialogResult == DialogResult.Abort)
					{
						try
						{
							XYZ startPnt = base.Sel.PickPoint("请选择第一点……");
							XYZ endPnt = base.Sel.PickPoint("请选择第二点……");
							double num = Convert.ToDouble(StringTools.CutOffEfficacious(plumbSystemAutoDesign.GetLineToXAngle(startPnt, endPnt).ToString(), 1));
							if (formAutoDesign.bAngle)
							{
								formAutoDesign.SetWAngle(num);
							}
							else
							{
								formAutoDesign.SetFAngle(num);
							}
						}
						catch (Exception)
						{
						}
					}
					if (dialogResult == DialogResult.Yes)
					{
						break;
					}
					if (dialogResult == DialogResult.Cancel)
					{
						goto Block_24;
					}
				}
				bool designStyle = formAutoDesign.GetDesignStyle();
				bool splitFlow = formAutoDesign.GetSplitFlow();
				List<Element> list;
				for (;;)
				{
					list = this.SelectingElements(designStyle, splitFlow);
					if (formAutoDesign.IsSeleLinkBath())
					{
						List<Element> collection = HYPlumbingAutoDesignNew.SelectingLinkElements(base.UiDoc, true, false);
						list.AddRange(collection);
					}
					string text = plumbSystemAutoDesign.CheckElements(list, designStyle, splitFlow);
					if (!(text != ""))
					{
						break;
					}
					YJKMessageBox.Information(text);
					RevitVersionFuncs.ClearSelection(base.Sel);
				}
				double wangle = formAutoDesign.GetWAngle();
				XYZ pipeLineVector = plumbSystemAutoDesign.GetPipeLineVector(wangle * Math.PI / 180.0);
				double wpipeDiameter = formAutoDesign.GetWPipeDiameter();
				double slope = formAutoDesign.GetWPipeSlope() / 100.0;
				double offset = formAutoDesign.GetWPipeStartOffset() * 1000.0;
				double fangle = formAutoDesign.GetFAngle();
				XYZ pipeLineVector2 = plumbSystemAutoDesign.GetPipeLineVector(fangle * Math.PI / 180.0);
				double fpipeDiameter = formAutoDesign.GetFPipeDiameter();
				double slope2 = formAutoDesign.GetFPipeSlope() / 100.0;
				double offset2 = formAutoDesign.GetFPipeStartOffset() * 1000.0;
				List<Pipe> list2 = new List<Pipe>();
				List<FamilyInstance> list3 = new List<FamilyInstance>();
				foreach (Element element in list)
				{
					if (element is Pipe)
					{
						list2.Add(element as Pipe);
					}
					if (element is FamilyInstance)
					{
						ConnectorManager connectorManager = (element as FamilyInstance).MEPModel.ConnectorManager;
						if (connectorManager != null)
						{
							ConnectorSet connectors = connectorManager.Connectors;
							if (connectors != null && connectors.Size > 0)
							{
								ConnectorSetIterator connectorSetIterator = connectors.ForwardIterator();
								int num2 = 0;
								while (connectorSetIterator.MoveNext())
								{
									object obj = connectorSetIterator.Current;
									Connector connector = obj as Connector;
									if (connector != null && 3 == (int)connector.Domain && (int)connector.Direction == 2)
									{
										num2++;
									}
								}
								if (num2 > 0)
								{
									list3.Add(element as FamilyInstance);
								}
							}
						}
					}
				}
				this.tran = new Transaction(base.Doc, "排水自动设计");
				this.tran.Start();
				int num3 = 0;
                Autodesk.Revit.DB.Plumbing.PipeType wpipeType = formAutoDesign.GetWPipeType();
                Autodesk.Revit.DB.Plumbing.PipeType fpipeType = formAutoDesign.GetFPipeType();
				if (splitFlow)
				{
					List<FamilyInstance> list4 = new List<FamilyInstance>();
					List<FamilyInstance> list5 = new List<FamilyInstance>();
					Pipe pipe = null;
					Pipe pipe2 = null;
					foreach (Pipe pipe3 in list2)
					{
						if (pipe3.GetParameter(BuiltInParameter.RBS_PIPING_SYSTEM_TYPE_PARAM).AsValueString().Contains("污水"))
						{
							pipe = pipe3;
						}
						else
						{
							pipe2 = pipe3;
						}
					}
					if (pipe == null)
					{
						pipe = list2[0];
						pipe2 = list2[1];
					}
					foreach (FamilyInstance familyInstance in list3)
					{
						SetSanitaryData setSanitaryData = YJKRevitTools.GetSetSanitaryData(base.Doc, familyInstance);
						if (setSanitaryData != null)
						{
							string sanitaryType = setSanitaryData.SanitaryType;
							if (sanitaryType == "坐便器" || sanitaryType == "小便器" || sanitaryType == "蹲便器(自闭式)" || sanitaryType == "蹲便器(水箱)")
							{
								list4.Add(familyInstance);
							}
							else
							{
								list5.Add(familyInstance);
							}
						}
						else
						{
							list5.Add(familyInstance);
						}
					}
					if (designStyle)
					{
						if (list4.Count != 0 && pipe != null)
						{
							num3 += this.ConnRiserPipe(formAutoDesign, pipe, offset, list4, pipeLineVector, wpipeDiameter, slope, wpipeType);
						}
						if (list5.Count != 0 && pipe2 != null)
						{
							num3 += this.ConnRiserPipe(formAutoDesign, pipe2, offset2, list5, pipeLineVector2, fpipeDiameter, slope2, fpipeType);
						}
					}
					else
					{
						if (list4.Count != 0 && pipe != null)
						{
							num3 += this.ConnPipe(formAutoDesign, pipe, list4, pipeLineVector, wpipeDiameter, slope);
						}
						if (list5.Count != 0 && pipe2 != null)
						{
							num3 += this.ConnPipe(formAutoDesign, pipe2, list5, pipeLineVector2, fpipeDiameter, slope2);
						}
					}
				}
				else if (designStyle)
				{
					num3 += this.ConnRiserPipe(formAutoDesign, list2[0], offset, list3, pipeLineVector, wpipeDiameter, slope, wpipeType);
				}
				else
				{
					num3 += this.ConnPipe(formAutoDesign, list2[0], list3, pipeLineVector, wpipeDiameter, slope);
				}
				if (num3 > 0)
				{
					YJKMessageBox.Show("由于器具位置与管道位置不合适，\n造成" + num3 + "个器具没有连接成功。");
				}
				this.tran.Commit();
				RevitVersionFuncs.ClearSelection(base.Sel);
				formAutoDesign.Close();
				goto IL_54E;
				Block_24:
				formAutoDesign.Close();
				IL_54E:
				result = Autodesk.Revit.UI.Result.Succeeded;
			}
			catch (Autodesk.Revit.Exceptions.OperationCanceledException)
			{
				result = Autodesk.Revit.UI.Result.Succeeded;
			}
			catch (Exception ex)
			{
				YJKMessageBox.Information(ex.Message);
				result = Autodesk.Revit.UI.Result.Failed;
			}
			finally
			{
				if (this.tran != null)
				{
					TransactionStatus status = this.tran.GetStatus();
					if ((int)status == 1)
					{
						this.tran.Commit();
					}
					else if ((int)status == 5)
					{
						this.tran.RollBack();
					}
				}
			}
			return result;
		}

        private int ConnRiserPipe(FormAutoDesign fad, Pipe pipe, double offset, List<FamilyInstance> listFi, XYZ pipeVector, double diameter, double slope, Autodesk.Revit.DB.Plumbing.PipeType pipeType)
		{
			XYZ originalPnt = null;
			string text = "";
			YJKPipeConnectorHelper hypipeConnectorHelper = new YJKPipeConnectorHelper();
			PlumbSystemAutoDesign plumbSystemAutoDesign = new PlumbSystemAutoDesign(base.Doc);
			FamilySymbol teeFamilySymbol = plumbSystemAutoDesign.GetTeeFamilySymbol("顺水三通", base.Doc, ref text);
			List<FamilyInstance> list = plumbSystemAutoDesign.orderFamilyInstance(pipe, offset, listFi, ref originalPnt);
			Pipe pipe2 = plumbSystemAutoDesign.CreatHorizontalPipe(pipe, offset, list, pipeVector, diameter, slope);
			if (pipeType != null)
			{
				pipe2.PipeType = pipeType;
			}
			if (pipe2 == null)
			{
				throw new Exception("卫生设备出口连接口未找到，\n可能是由于出口Connector的流体走向不是'out'造成的。");
			}
			pipe = plumbSystemAutoDesign.CheckAndExtendPipe(pipe, offset);
			base.Doc.Regenerate();
			hypipeConnectorHelper.TPipeConnectRPipe(pipe, pipe2, base.Doc, teeFamilySymbol, true, ref text, false, 0.0);
			return this.PipeConnEquipment(pipe2, list, fad, originalPnt);
		}

		private int ConnPipe(FormAutoDesign fad, Pipe pipe, List<FamilyInstance> listFi, XYZ pipeVector, double diameter, double slope)
		{
			XYZ xyz = null;
			Pipe pipe2 = pipe;
			YJKPipeConnectorHelper hypipeConnectorHelper = new YJKPipeConnectorHelper();
			PlumbSystemAutoDesign plumbSystemAutoDesign = new PlumbSystemAutoDesign(base.Doc);
			plumbSystemAutoDesign.JudgeBeDrawPipe(pipe2, listFi, ref xyz);
			List<FamilyInstance> list = plumbSystemAutoDesign.orderFamilyInstance(xyz, listFi);
			if (fad.GetBeDrawPipe())
			{
				pipe2 = plumbSystemAutoDesign.CreatHorizontalPipe(pipe2, xyz, list, pipeVector, diameter, slope);
				if (pipe2 == null)
				{
					throw new Exception("卫生设备出口连接口未找到，\n可能是由于出口Connector的流体走向不是'out'造成的。");
				}
				XYZ xyz2 = null;
				XYZ xyz3 = null;
				if (plumbSystemAutoDesign.BeConnPipes(pipe, pipe2, xyz, ref xyz2, ref xyz3))
				{
					hypipeConnectorHelper.connect45Elbow(pipe, xyz2, pipe2, xyz3, base.Doc);
				}
			}
			Pipe connPipe = plumbSystemAutoDesign.ExtendBasePipe(pipe2, list, ref xyz);
			return this.PipeConnEquipment(connPipe, list, fad, xyz);
		}

		private int PipeConnEquipment(Pipe connPipe, List<FamilyInstance> listFamily, FormAutoDesign fad, XYZ originalPnt)
		{
			string text = "";
			FamilySymbol teeFamilySymbol = new PlumbSystemAutoDesign(base.Doc).GetTeeFamilySymbol("顺水三通", base.Doc, ref text);
			AutoDesignHelper autoDesignHelper = new AutoDesignHelper();
			Pipe pipe = connPipe;
			int num = 0;
			if (listFamily != null)
			{
				foreach (FamilyInstance fi in listFamily)
				{
					FamilySymbol accessory = this.GetAccessory(base.Doc, fad, fi, ref text);
					string value = "";
					List<Pipe> list = autoDesignHelper.PipeConnectLinkEquipment(base.UiDoc.Document, fi, pipe, teeFamilySymbol, accessory, true, ref value);
					if (!string.IsNullOrEmpty(value))
					{
						num++;
					}
					double num2 = -1.0;
					if (list != null && list.Count > 0)
					{
						YJKRotateFamilyInstance hyrotateFamilyInstance = new YJKRotateFamilyInstance();
						foreach (Pipe pipe2 in list)
						{
							YJKPiping<Pipe> hypiping = new YJKPiping<Pipe>(pipe2);
							hyrotateFamilyInstance.MovePiping(pipe2);
							double distanceSumEnd = hypiping.GetDistanceSumEnd(originalPnt);
							if (num2 < distanceSumEnd)
							{
								pipe = pipe2;
								num2 = distanceSumEnd;
							}
						}
					}
				}
			}
			return num;
		}

		public static bool IsLinkBathroom(Element ent, bool bCondl)
		{
			if (!(ent is FamilyInstance))
			{
				return false;
			}
			if (!ent.Document.IsLinked)
			{
				return false;
			}
			if (DbUtils.IsPlumbingFixtures(ent))
			{
				return true;
			}
			if (!bCondl)
			{
				return false;
			}
			if (DbUtils.IsPipeAccessory(ent))
			{
				if ((ent as FamilyInstance).Symbol.Family.Name.Contains("地漏") || (ent as FamilyInstance).Symbol.Name.Contains("地漏"))
				{
					return true;
				}
				if ((ent as FamilyInstance).Symbol.Family.Name.Contains("洗衣机") || (ent as FamilyInstance).Symbol.Name.Contains("洗衣机"))
				{
					return true;
				}
			}
			return false;
		}

		public static List<Element> SelectingLinkElements(UIDocument UiDoc, bool bCon, bool waterSupply = true)
		{
			List<Element> list = new List<Element>();
			string prompt = "请选链接文档中的卫浴";
			try
			{
                List<Element> list2 = UiDoc.PickLinkElements<Element>(prompt);
				if (list2 == null)
				{
					return list;
				}
				using (List<Element>.Enumerator enumerator = list2.GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						Element elem = enumerator.Current;
						if (HYPlumbingAutoDesignNew.IsLinkBathroom(elem, bCon))
						{
							ConnectorManager connectorManager = (elem as FamilyInstance).MEPModel.ConnectorManager;
							if (connectorManager != null)
							{
								ConnectorSet connectors = connectorManager.Connectors;
								if (connectors != null && connectors.Size > 0)
								{
									if (!waterSupply)
									{
										ConnectorSetIterator connectorSetIterator = connectors.ForwardIterator();
										int num = 0;
										while (connectorSetIterator.MoveNext())
										{
											object obj = connectorSetIterator.Current;
											Connector connector = obj as Connector;
											if (connector != null && 3 == (int)connector.Domain && (int)connector.Direction == 2)
											{
												num++;
											}
										}
										if (num > 0 && list.Find((Element sr) => sr.Id == elem.Id) == null)
										{
											list.Add(elem as FamilyInstance);
										}
									}
									else if (list.Find((Element sr) => sr.Id == elem.Id) == null)
									{
										list.Add(elem as FamilyInstance);
									}
								}
							}
						}
					}
				}
			}
			catch (Exception)
			{
			}
			return list;
		}

		private List<Element> SelectingElements(bool beRiser, bool bSplitFlow)
		{
			ISelectionFilter selectionFilter;
			string text;
			if (beRiser)
			{
				selectionFilter = new AutoDesignRiserPipe(true);
				if (bSplitFlow)
				{
					text = "请选择排水系统设计需要的实体：两根水管立管、若干卫生设备……";
				}
				else
				{
					text = "请选择排水系统设计需要的实体：一根水管立管、若干卫生设备……";
				}
			}
			else
			{
				selectionFilter = new AutoDesignCommonPipe(true);
				if (bSplitFlow)
				{
					text = "请选择排水系统设计需要的实体：两根横管、若干卫生设备……";
				}
				else
				{
					text = "请选择排水系统设计需要的实体：一根横管、若干卫生设备……";
				}
			}
			List<Element> list = null;
			new PlumbSystemAutoDesign(base.Doc);
			list = new List<Element>();
			if (base.Sel.GetElementIds().Count > 0)
			{
				IEnumerator<ElementId> enumerator = base.Sel.GetElementIds().GetEnumerator();
				{
					while (enumerator.MoveNext())
					{
						ElementId elementId = enumerator.Current;
						list.Add(base.Doc.GetElementById(elementId));
					}
					return list;
				}
			}
			foreach (Reference reference in base.Sel.PickObjects((Autodesk.Revit.UI.Selection.ObjectType)1, selectionFilter, text))
			{
				list.Add(base.Doc.GetElement(reference));
			}
			return list;
		}

		private FamilySymbol GetAccessory(Autodesk.Revit.DB.Document doc, FormAutoDesign fad, FamilyInstance fi, ref string loadMSG)
		{
			FamilySymbol result = null;
			PlumbSystemAutoDesign plumbSystemAutoDesign = new PlumbSystemAutoDesign(doc);
			SetSanitaryData setSanitaryData = YJKRevitTools.GetSetSanitaryData(doc, fi);
			if (setSanitaryData != null)
			{
				int trap = setSanitaryData.Trap;
				if (trap != 1)
				{
					if (trap == 2)
					{
						result = plumbSystemAutoDesign.GetTeeFamilySymbol("180°P型存水弯", doc, ref loadMSG);
					}
					else
					{
						result = null;
					}
				}
				else
				{
					result = plumbSystemAutoDesign.GetTeeFamilySymbol("180°S型存水弯", doc, ref loadMSG);
				}
			}
			return result;
		}

		public override void TailProcess()
		{
			if (this.tran != null)
			{
				TransactionStatus status = this.tran.GetStatus();
				if ((int)status == 1)
				{
					this.tran.Commit();
				}
				if ((int)status == 5)
				{
					this.tran.RollBack();
				}
			}
		}

		private Transaction tran;
	}
}
